package com.java.create;

import java.util.concurrent.*;

/**
 * 利用Callable接口和FutureTask接口创建线程
 * 1、实现Callable接口并重写call()，call()返回值表示线程运行结果
 * 2、实例化Callable实现类并传递给FutureTask类
 * 3、实例化FutureTask类并传递给Thread类，用于管理线程运行结果
 * 4、实例化Thread类并start()启动线程
 */
public class CallableFutureTaskCreate {
    static class CallableSon implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println("线程(" + Thread.currentThread().getName() + ")开始");

            for (int i = 0; i < 5; i++) {
                System.out.println("线程(" + Thread.currentThread().getName() + ")运行中");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    return "失败";
                }
            }

            System.out.println("线程(" + Thread.currentThread().getName() + ")结束");

            return "成功";
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        System.out.println("主线程开始");

        CallableSon callableSon1 = new CallableSon();
        FutureTask futureTask1 = new FutureTask(callableSon1);
        new Thread(futureTask1).start();

        CallableSon callableSon2 = new CallableSon();
        FutureTask futureTask2 = new FutureTask(callableSon2);
        new Thread(futureTask2).start();

        // get：获取线程结果并阻塞当前线程，直到call返回结果或抛出异常后再放行。设置超时时间若超时则抛出异常TimeoutException
        System.out.println("线程结果：" + futureTask1.get());
        System.out.println("线程结果：" + futureTask2.get(500, TimeUnit.MILLISECONDS));

        // cancel：取消线程，返回值表示是否取消成功。若参数为true则直接中断该线程，参数为false则运行完后中断该线程
        System.out.println("取消线程：" + futureTask1.cancel(true)); // false

        for (int i = 0; i < 5; i++) {
            System.out.println("主线程运行中");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("主线程结束");
    }

    /**
     * 输出结果如下，每次运行的结果不同！但"主线程开始"一定在最开始
     * 主线程开始
     * 线程(Thread-0)开始
     * 线程(Thread-0)运行中
     * 线程(Thread-1)开始
     * 线程(Thread-1)运行中
     * 线程(Thread-0)运行中
     * 线程(Thread-1)运行中
     * 线程(Thread-1)运行中
     * 线程(Thread-0)运行中
     * 线程(Thread-1)运行中
     * 线程(Thread-0)运行中
     * 线程(Thread-1)运行中
     * 线程(Thread-0)运行中
     * 线程(Thread-1)结束
     * 线程(Thread-0)结束
     * 线程结果：成功
     * 线程结果：成功
     * 取消线程：false
     * 主线程运行中
     * 主线程运行中
     * 主线程运行中
     * 主线程运行中
     * 主线程运行中
     * 主线程结束
     */
}
